#ifndef __UP_SEVER_HPP__
#define __UP_SEVER_HPP__
#include <iostream>
#include <string>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <functional>
#include "Logger.hpp"
#include "Common.hpp"
#include "Inet_host.hpp"
#include "ThreadPool.hpp"
#include "User.hpp"

using namespace ThreadPoolMudule;
using namespace LogMudule;

const static int defsockfd = -1;
const static u_int16_t defport = 8888;
const static int defsize = 1024;

using adduser_t = std::function<void(InetAddr &id)>;
using deluser_t = std::function<void(InetAddr &id)>;
using route_t = std::function<void(int sockfd, const std::string &message)>;
using task_t = std::function<void()>;

class UdpSever
{
public:
    UdpSever(u_int16_t port = defport)
        :  _inet_addr(port),
          _isrunning(false),
          _sockfd(defsockfd)
    {
    }

    void SeverInit()
    {
        // 创建套接字
        _sockfd = ::socket(AF_INET, SOCK_DGRAM, 0);
        if (_sockfd < 0)
        {
            LOG(LogLevel::FATAL) << "sock :" << strerror(SOCKET_ERR);
            Die(SOCKET_ERR);
        }

        LOG(LogLevel::INFO) << "sock sucess.";

        InetAddr inetlocal(_inet_addr);

        int n = ::bind(_sockfd, inetlocal.SockAddr(), inetlocal.SockLen());
        if (n < 0)
        {
            LOG(LogLevel::FATAL) << "bind :" << strerror(BIND_ERR);
            Die(BIND_ERR);
        }
        LOG(LogLevel::INFO) << "bind sucess.";
    }
    void RegisterTask(adduser_t add, deluser_t del, route_t route)
    {
        _add = add;
        _del = del;
        _route = route;
    }
    void Start()
    {
        _isrunning = true;
        while (true)
        {
            char inbuffer[defsize];
            // 设定接受值
            struct sockaddr_in peer;
            socklen_t peer_len = sizeof(peer);

            int n = ::recvfrom(_sockfd, inbuffer, sizeof(inbuffer) - 1, 0, Conv(&peer), &peer_len);
            if (n > 0)
            {
                InetAddr cil(peer);
                inbuffer[n] = 0;
                std::string message;
                //判断是否退出
                if(strcmp(inbuffer,"QUIT") == 0)
                {
                    //移除观察者
                    _del(cil);
                    message = cil.Addr() + ":" + "我走了，你们聊!"; 
                }
                else
                {
                    //新增用户
                    _add(cil);
                    message = cil.Addr() + "# " + inbuffer;
                }
                //构建转发任务
                LOG(LogLevel::DEBUG)<<message;
                task_t task = std::bind(_route,_sockfd,message);
                ThreadPool<task_t>::getInstance()->Equeue(task);
            } 
        }
        _isrunning = false;
    }
    ~UdpSever()
    {
        if (_sockfd > defsockfd)
            ::close(_sockfd);
    }

private:
    int _sockfd; // 套接字文件描述符
    InetAddr _inet_addr;
    bool _isrunning; // 运行状态

    // 任务
    // 增加用户
    adduser_t _add;
    // 删除用户
    deluser_t _del;
    // 转发任务
    route_t _route;
};

#endif